package org.fisco.bcos.evidence.client;

import org.fisco.bcos.evidence.bean.Account;
import org.fisco.bcos.evidence.contract.AccountKV;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple5;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

import java.math.BigInteger;

/// 统一存证平台 - 账户合约

/**
 * 添加账户 setAccount
 * 获取账户 getAccount
 */
@Service
public class AccountKVClient {
    static Logger logger = LoggerFactory.getLogger(AccountKVClient.class);

    @Autowired
    private BcosConnnection bcosConnnection;

    @Autowired
    private ShaTestClient shaTestClient;

    @Value("${contract.account_kv.address}")
    protected String contractAddress;


//    public void setCrypto(ShaTestClient shaTestClient) {
//        this.shaTestClient = shaTestClient;
//    }

//    /**
//     * 2. 构造合约类对象 - 部署合约
//     */
//    public void deployAccountKV() {
//        try {
//            AccountKV accountKV = AccountKV.deploy(bcosConnnection.client, bcosConnnection.cryptoKeyPair);
//            System.out.println(" deploy AccountKV success, contract address is " + accountKV.getContractAddress());
//            contractAddress = accountKV.getContractAddress();
//        } catch (Exception e) {
//            System.out.println(" deploy AccountKV contract failed, error message is  " + e.getMessage());
//        }
//    }


    /**
     * 3. 接口调用
     * <p>
     * 使用合约对象调用对应的接口，处理返回结果。
     * // get 接口调用
     * function get(string memory id) public view returns
     * (bool, string memory,string memory,string memory,string memory) {
     */
    public Account getAccount(String id) {
        logger.info("AccountKVClient contractAddress = " + contractAddress);
        Account account = null;

        try {
            ///加载合约地址
            AccountKV accountKV = AccountKV.load(contractAddress, bcosConnnection.client, bcosConnnection.cryptoKeyPair);
            Tuple5<Boolean, String, String, String, String> result = accountKV.get(id);

            if (result.getValue1()) {
                ///id, identity, name, accountType, accountHash
                account = new Account();
                account.setId(id);
                account.setIdentity(result.getValue2());
                account.setName(result.getValue3());
                account.setAccountType(result.getValue4());
                account.setAccountHash(result.getValue5());
            } else {
                System.out.printf(" %s account is not exist \n", accountKV);
            }

        } catch (Exception e) {
            logger.error(" queryAccountKVAmount exception, error message is {}", e.getMessage());
            System.out.printf(" query AccountKV account failed, error message is %s\n", e.getMessage());
        }
        return account;
    }


    /**
     * 3. 接口调用
     * <p>
     * 使用合约对象调用对应的接口，处理返回结果。
     * function set(string memory id, string memory identity, string memory name, string memory accountType, string memory accountHash)
     * public
     * returns (int256)
     */
    public boolean setAccount(Account account) {
        logger.info("AccountKVClient contractAddress = " + contractAddress);

        try {
            AccountKV accountKV = AccountKV.load(contractAddress, bcosConnnection.client, bcosConnnection.cryptoKeyPair);

            /// 计算 Keccak256 Hash 值
            StringBuilder builder = new StringBuilder();
            builder.append(account.getId()).
                    append(account.getIdentity()).
                    append(account.getName()).
                    append(account.getAccountType());
            account.setAccountHash(shaTestClient.getKeccak256(builder.toString()));

            logger.info("src=" + builder.toString());
            logger.info("hash=" + account.getAccountHash());

            TransactionReceipt receipt = accountKV.set(account.getId(), account.getIdentity(),
                    account.getName(), account.getAccountType(), account.getAccountHash());

            Tuple1<BigInteger> retOutput = accountKV.getSetOutput(receipt);
            BigInteger ret = retOutput.getValue1();
            System.out.printf("ret =" + ret);

            return (ret.intValue() > 0) ? true : false;
        } catch (Exception e) {
            logger.error(" registerAccountKVAccount exception, error message is {}", e.getMessage());
            System.out.printf(" register AccountKV account failed, error message is %s\n", e.getMessage());
        }
        return false;
    }

//
//    public static void main(String[] args) throws Exception {
//
//        AccountKVClient client = new AccountKVClient();
//        client.initialize();
//        client.deployAccountKV();
//
//        Account account = new Account();
//        account.setId("0x99100");
//        account.setIdentity("1010101010101010");
//        account.setName("Jone");
//        account.setAccountType("Person");
//        account.setAccountHash("0x121212121112121212");
//
//        System.out.printf("set: " + client.setAccount(account));
//
//        Account ret = client.getAccount("0x99100");
//        System.out.printf("get: "+ ret.toString());
//
//
//        System.exit(0);
//    }

}


//
//public class AccountKVClient {
//    static Logger logger = LoggerFactory.getLogger(AccountKVClient.class);
//
//    private BcosSDK bcosSDK;
//    private Client client;
//    private CryptoKeyPair cryptoKeyPair;
//    private String contractAddress = null;
//
//    /**
//     * 1. 初始化代码
//     * 主要功能为构造Client与CryptoKeyPair对象，这两个对象在创建对应的合约类对象(调用合约类的deploy或者load函数)时需要使用。
//     * */
//    public void initialize() throws Exception {
//        // 函数initialize中进行初始化
//        // 初始化BcosSDK
//        @SuppressWarnings("resource")
//        ApplicationContext context =
//                new ClassPathXmlApplicationContext("classpath:fisco-config.xml");
//        bcosSDK = context.getBean(BcosSDK.class);
//        client = bcosSDK.getClient(1);
//        cryptoKeyPair = client.getCryptoSuite().createKeyPair();
//        client.getCryptoSuite().setCryptoKeyPair(cryptoKeyPair);
//        logger.debug("create client for group1, account address is " + cryptoKeyPair.getAddress());
//    }
//
//    /**
//     * 2. 构造合约类对象 - 部署合约
//     *  */
//    public void deployAccountKV() {
//        try {
//            AccountKV accountKV = AccountKV.deploy(client, cryptoKeyPair);
//            System.out.println(" deploy AccountKV success, contract address is " + accountKV.getContractAddress());
//            contractAddress = accountKV.getContractAddress();
//        } catch (Exception e) {
//            System.out.println(" deploy AccountKV contract failed, error message is  " + e.getMessage());
//        }
//    }
//
//
//    /**
//     * 3. 接口调用
//     *
//     * 使用合约对象调用对应的接口，处理返回结果。
//     *  // get 接口调用
//     *      function get(string memory id) public view returns
//     *      (bool, string memory,string memory,string memory,string memory) {
//     * */
//    public Account getAccount(String id) {
//        Account account = new Account();
//
//        try {
//            ///加载合约地址
//            AccountKV accountKV = AccountKV.load(contractAddress, client, cryptoKeyPair);
//            Tuple5<Boolean, String, String, String, String> result = accountKV.get(id);
//
//            if (result.getValue1()) {
//                ///id, identity, name, accountType, accountHash
//                account.setId(id);
//                account.setIdentity(result.getValue2());
//                account.setName(result.getValue3());
//                account.setAccountType(result.getValue4());
//                account.setAccountHash(result.getValue5());
//            }else{
//                System.out.printf(" %s account is not exist \n", accountKV);
//            }
//
//        } catch (Exception e) {
//            logger.error(" queryAccountKVAmount exception, error message is {}", e.getMessage());
//            System.out.printf(" query AccountKV account failed, error message is %s\n", e.getMessage());
//        }
//        return account;
//    }
//
//
//
//    /**
//     * 3. 接口调用
//     *
//     * 使用合约对象调用对应的接口，处理返回结果。
//     *     function set(string memory id, string memory identity, string memory name, string memory accountType, string memory accountHash)
//     *     public
//     *     returns (int256)
//     * */
//    public boolean setAccount(Account account) {
//        try {
//            AccountKV accountKV = AccountKV.load(contractAddress, client, cryptoKeyPair);
//            TransactionReceipt receipt = accountKV.set(account.getId(), account.getIdentity(),
//                    account.getName(), account.getAccountType(), account.getAccountHash());
//
//            Tuple1<BigInteger> retOutput =  accountKV.getSetOutput(receipt);
//            BigInteger ret = retOutput.getValue1();
//            System.out.printf("ret ="+ret);
//
//            return (ret.intValue()>0)? true: false;
//        } catch (Exception e) {
//            logger.error(" registerAccountKVAccount exception, error message is {}", e.getMessage());
//            System.out.printf(" register AccountKV account failed, error message is %s\n", e.getMessage());
//        }
//        return false;
//    }
//
//
//    public static void main(String[] args) throws Exception {
//
//        AccountKVClient client = new AccountKVClient();
//        client.initialize();
//        client.deployAccountKV();
//
//        Account account = new Account();
//        account.setId("0x99100");
//        account.setIdentity("1010101010101010");
//        account.setName("Jone");
//        account.setAccountType("Person");
//        account.setAccountHash("0x121212121112121212");
//
//        System.out.printf("set: " + client.setAccount(account));
//
//        Account ret = client.getAccount("0x99100");
//        System.out.printf("get: "+ ret.toString());
//
//
//        System.exit(0);
//    }
//
//}
